package com.example.mqttclient;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import com.example.mqttclient.mqtt.MqttService;
import com.example.mqttclient.protocol.AirConditioningMesssage;
import com.example.mqttclient.protocol.BoolMessage;
import com.example.mqttclient.protocol.FloatMessage;
import com.example.mqttclient.protocol.IntMessage;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.google.gson.Gson;
import org.eclipse.paho.client.mqttv3.MqttException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DevicesDemoActivity extends AppCompatActivity implements MqttService.MqttEventCallBack,
        CompoundButton.OnCheckedChangeListener {
    private TextView connectState, temperatureValue, humidityValue, pmValue, gasValue, doorStatus;
    private EditText airConditioningValue;
    private MqttService.MqttBinder mqttBinder;
    private String TAG = "DevicesDemoActivity";
    private Switch parlourLightSwitch, curtainSwitch, fanSocketSwitch, airConditioningSwitch;
    private Map<String, Integer> subscribeTopics = new HashMap<>();
    private LineChart sensorChart;
    private LineData chartData;
    private NotificationManager notificationManager;
    private int notificationId = 1;
    private static final String CHANNEL_ID = "smart_home_channel";
    private TextToSpeech textToSpeech;
    private SeekBar fanSpeedSeekBar;
    private TextView fanSpeedText;
    private int currentTheme = R.style.AppTheme;

    private List<Entry> temperatureEntries = new ArrayList<>();
    private List<Entry> humidityEntries = new ArrayList<>();
    private List<Entry> pmEntries = new ArrayList<>();
    private List<Entry> gasEntries = new ArrayList<>();
    private int dataIndex = 0;

    private static final int GAS_ALERT_THRESHOLD = 80; // 可燃气体浓度报警阈值

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mqttBinder = (MqttService.MqttBinder) iBinder;
            mqttBinder.setMqttEventCallback(DevicesDemoActivity.this);
            if (mqttBinder.isConnected()) {
                connectState.setText("已连接");
                subscribeTopics();
            } else {
                connectState.setText("未连接");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_devices_demo);

        connectState = findViewById(R.id.dev_connect_state);

        Intent mqttServiceIntent = new Intent(this, MqttService.class);
        bindService(mqttServiceIntent, connection, Context.BIND_AUTO_CREATE);

        temperatureValue = findViewById(R.id.temperature_value);
        humidityValue = findViewById(R.id.humidity_value);
        pmValue = findViewById(R.id.pm_value);
        gasValue = findViewById(R.id.gas_value);
        doorStatus = findViewById(R.id.door_status);
        airConditioningValue = findViewById(R.id.air_conditioning_value);

        parlourLightSwitch = findViewById(R.id.parlour_light_switch);
        parlourLightSwitch.setOnCheckedChangeListener(this);
        curtainSwitch = findViewById(R.id.curtain_switch);
        curtainSwitch.setOnCheckedChangeListener(this);
        fanSocketSwitch = findViewById(R.id.fan_socket_switch);
        fanSocketSwitch.setOnCheckedChangeListener(this);
        airConditioningSwitch = findViewById(R.id.air_conditioning_switch);
        airConditioningSwitch.setOnCheckedChangeListener(this);

        sensorChart = findViewById(R.id.sensorChart);
        initChart();

        createNotificationChannel();
        // 模拟获取天气信息并推送通知
        showWeatherNotification();
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = getString(R.string.channel_name);
            String description = getString(R.string.channel_description);
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
            channel.setDescription(description);
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    private void showGasAlertNotification(int gasConcentration) {
        Intent intent = new Intent(this, DevicesDemoActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle("可燃气体浓度过高！")
                .setContentText("当前可燃气体浓度为: " + gasConcentration + "%LEL，请及时处理！")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(notificationId++, builder.build());
    }

    private void showWeatherNotification() {
        // 假设这里调用 WeatherApi 获取天气信息
        String weatherInfo = WeatherApi.getWeatherInfo("beijing");

        Intent intent = new Intent(this, DevicesDemoActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle("当前天气信息")
                .setContentText(weatherInfo)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(notificationId++, builder.build());
    }

    private void initChart() {
        // 设置 X 轴
        XAxis xAxis = sensorChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setGranularity(1f);
        xAxis.setValueFormatter(new ValueFormatter() {
            @Override
            public String getAxisLabel(float value, AxisBase axis) {
                return String.valueOf((int) value);
            }
        });

        // 创建空的 LineData
        chartData = new LineData();
        sensorChart.setData(chartData);
        sensorChart.invalidate();
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
        switch (compoundButton.getId()) {
            case R.id.parlour_light_switch:
                try {
                    if (compoundButton.isChecked()) {
                        mqttBinder.publishMessage("/test/light1",
                                new Gson().toJson(new BoolMessage(true)));
                    } else {
                        mqttBinder.publishMessage("/test/light1",
                                new Gson().toJson(new BoolMessage(false)));
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;

            case R.id.curtain_switch:
                try {
                    if (compoundButton.isChecked()) {
                        mqttBinder.publishMessage("/test/curtain1",
                                new Gson().toJson(new BoolMessage(true)));
                    } else {
                        mqttBinder.publishMessage("/test/curtain1",
                                new Gson().toJson(new BoolMessage(false)));
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;

            case R.id.fan_socket_switch:
                try {
                    if (compoundButton.isChecked()) {
                        mqttBinder.publishMessage("/test/fan1",
                                new Gson().toJson(new BoolMessage(true)));
                    } else {
                        mqttBinder.publishMessage("/test/fan1",
                                new Gson().toJson(new BoolMessage(false)));
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;

            case R.id.air_conditioning_switch:
                try {
                    if (compoundButton.isChecked()) {
                        String json = new Gson().toJson(new AirConditioningMesssage(true,
                                Float.parseFloat(airConditioningValue.getText().toString())));
                        Log.d("json", json);
                        mqttBinder.publishMessage("/test/airConditioning", json);
                    } else {
                        String json = new Gson().toJson(new AirConditioningMesssage(false,
                                Float.parseFloat(airConditioningValue.getText().toString())));
                        Log.d("json", json);
                        mqttBinder.publishMessage("/test/airConditioning", json);
                    }
                } catch (MqttException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    void unSubscribeTopics() {
        try {
            for (Map.Entry<String, Integer> entry : subscribeTopics.entrySet()) {
                mqttBinder.unSubscribe(entry.getKey());
            }
            subscribeTopics.clear();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectSuccess() {
        subscribeTopics();
        connectState.setText("已连接");
    }

    @Override
    public void onConnectError(String error) {
        Log.d(TAG, "onConnectError: " + error);
        connectState.setText("未连接");
        subscribeTopics.clear();
    }

    @Override
    public void onDeliveryComplete() {
        Log.d(TAG, "publish ok");
    }

    @Override
    public void onMqttMessage(String topic, String message) {
        Log.d("onMqttMessage", "topic:" + topic + " message length:" + message.length() + "，message:" + message);
        Gson gson = new Gson();
        switch (subscribeTopics.get(topic)) {
            case 1:
                float temperature = gson.fromJson(message.trim(), FloatMessage.class).value;
                temperatureValue.setText(String.valueOf(temperature));
                temperatureEntries.add(new Entry(dataIndex, temperature));
                updateChartData(temperatureEntries, "温度");
                break;
            case 2:
                int humidity = gson.fromJson(message.trim(), IntMessage.class).value;
                humidityValue.setText(String.valueOf(humidity));
                humidityEntries.add(new Entry(dataIndex, humidity));
                updateChartData(humidityEntries, "湿度");
                break;
            case 3:
                int pm = gson.fromJson(message.trim(), IntMessage.class).value;
                pmValue.setText(String.valueOf(pm));
                pmEntries.add(new Entry(dataIndex, pm));
                updateChartData(pmEntries, "PM2.5");
                break;
            case 4:
                int gas = gson.fromJson(message.trim(), IntMessage.class).value;
                gasValue.setText(String.valueOf(gas));
                gasEntries.add(new Entry(dataIndex, gas));
                updateChartData(gasEntries, "可燃气体浓度");
                if (gas > GAS_ALERT_THRESHOLD) {
                    showGasAlertNotification(gas);
                }
                break;
            case 5:
                String status = gson.fromJson(message.trim(), BoolMessage.class).value? "开" : "关";
                doorStatus.setText(status);
                break;
        }
        dataIndex++;
    }

    private void updateChartData(List<Entry> entries, String label) {
        LineDataSet dataSet = (LineDataSet) chartData.getDataSetByLabel(label, false);
        if (dataSet == null) {
            dataSet = new LineDataSet(entries, label);
            chartData.addDataSet(dataSet);
        } else {
            dataSet.setValues(entries);
        }
        chartData.notifyDataChanged();
        sensorChart.notifyDataSetChanged();
        sensorChart.invalidate();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        if (mqttBinder.isConnected()) {
            connectState.setText("已连接");
            subscribeTopics();
        } else {
            connectState.setText("未连接");
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        unSubscribeTopics();
    }

    @Override
    protected void onDestroy() {
        unbindService(connection);
        super.onDestroy();
    }

    void subscribeTopics() {
        try {
            subscribeTopics.put("/test/temp", 1);
            subscribeTopics.put("/test/hum", 2);
            subscribeTopics.put("/test/pm", 3);
            subscribeTopics.put("/test/gas", 4);
            subscribeTopics.put("/test/door", 5);
            for (Map.Entry<String, Integer> entry : subscribeTopics.entrySet()) {
                mqttBinder.subscribe(entry.getKey());
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}